package com.yangyang.rpc.core.registry.zookeeper;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * zookeeper服务发现
 * @author chenshunyang
 *
 */
public class ZkServiceDiscovery {
	 private static final Logger LOGGER = LoggerFactory.getLogger(ZkServiceDiscovery.class);

	 public static volatile ConcurrentHashMap<String,Set<String>> serviceAddress = new ConcurrentHashMap<>();


	public static void watchNode() {
        ConcurrentHashMap<String, Set<String>> tempMap = new ConcurrentHashMap<String, Set<String>>();
		try {
			final ZooKeeper zk = ZookeeperManager.getInstance();
			List<String> nodeList = zk.getChildren(Constant.ZK_REGISTRY_PATH, new Watcher(){

				@Override
				public void process(WatchedEvent event) {
					if (event.getType()== Event.EventType.NodeChildrenChanged) {
						watchNode();
					}
				}
				
			});
            if (nodeList!=null && nodeList.size() > 0) {
                for (String interfaceName :nodeList){
                    Set<String> addressSet = new HashSet<String>();
                    String ifacePath = Constant.ZK_REGISTRY_PATH + "/"+interfaceName;
                    // data from address
                    byte[] bytes = zk.getData(ifacePath, false, null);
                    addressSet.add(new String(bytes));
                    tempMap.put(interfaceName, addressSet);
                }
                serviceAddress = tempMap;
            }
			LOGGER.debug("Service discovery triggered updating connected server node.");
		} catch (KeeperException | InterruptedException e) {
			LOGGER.error("" ,e);
			e.printStackTrace();
		}
	}

	public static String discover(String interfaceName) {
		LOGGER.debug(">>>>>>>>>>>> discover:{}", interfaceName);
        watchNode();
		Set<String> addressSet = serviceAddress.get(interfaceName);
		if (addressSet==null || addressSet.size()==0) {
			return null;
		}
		String address;
		List<String> addressArr = new ArrayList<String>(addressSet);
		int size = addressSet.toArray().length;
		if (size == 1) {
			address = addressArr.get(0);
		} else {
			address = addressArr.get(new Random().nextInt(size));
		}
		return address;
	}

}
